package cn.iocoder.yudao.module.product.spu.convert;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.api.product.sku.dto.ProductPropertyValueRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuDetailRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuForUniAppRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuPageReqDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.api.promotion.groupon.dto.GrouponPackageRespDTO;
import cn.iocoder.yudao.module.product.sku.dal.dataobject.ProductSkuDO;
import cn.iocoder.yudao.module.product.sku.vo.AppProductSkuRespVO;
import cn.iocoder.yudao.module.product.sku.vo.AppProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.sku.vo.ProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.spu.dal.dataobject.ProductSpuDO;
import cn.iocoder.yudao.module.product.spu.vo.*;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.*;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMinValue;

/**
 * 产品 SPU Convert
 *
 * @author 芋道源码
 */
@Mapper
public interface ProductSpuConvert {

    ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);

    ProductSpuRespDTO convert(ProductSpuDO bean);

    ProductSpuDetailRespDTO convert2(ProductSpuDO bean);

    AppShopProductSpuDetailRespVO convert3(ProductSpuDO bean);

    AppProductSpuDetailRespVO convert(AppShopProductSpuDetailRespVO bean);

    AppProductSpuRespVO convert(AppProductSpuDetailRespVO bean);

    AppProductSkuRespVO convert(ProductSkuDO bean);

    ProductSpuDO convert(ProductSpuSaveReqVO bean);

    ProductSpuRespVO convertSpuVO(ProductSpuDO bean);

    ProductSkuRespVO convertSkuVO(ProductSkuDO bean);

    List<ProductSpuRespDTO> convertDTOList(List<ProductSpuDO> list);

    List<ProductSkuRespVO> convertSkuList(List<ProductSkuDO> list);

    PageResult<AppProductSpuRespVO> convertPage2(PageResult<ProductSpuDO> page);

    PageResult<ProductSpuRespDTO> convertPage(PageResult<AppProductSpuRespVO> page);

    AppProductSpuPageReqVO convert(ProductSpuPageReqDTO bean);

    ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);

    default ProductSpuRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus) {
        ProductSpuRespVO spuVO = convertSpuVO(spu);
        List<ProductSkuRespVO> skuList = convertSkuList(skus);
        skuList.forEach(sku -> {
            sku.setName(sku.getPropertiesValue());
            if (StrUtil.isBlank(sku.getPicUrl())) {
                sku.setPicUrl(spu.getPicUrl());
            }
        });
        spuVO.setSkus(skuList);
        return spuVO;
    }

    default List<ProductSpuRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
        Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
        return CollectionUtils.convertList(spus, spu -> convert(spu, skuMultiMap.get(spu.getId())));
    }

    ProductSpuSaveReqVO convert(AppProductSpuSaveReqVO bean);

    ProductSkuSaveReqVO convert(AppProductSkuSaveReqVO bean);

    /**
     * 将产品数据转换成前端想要的格式，可适配 UNIAPP 的 SKU 组件
     */
    default ProductSpuForUniAppRespDTO convert2(AppProductSpuRespVO bean) {
        ProductSpuForUniAppRespDTO respDTO = new ProductSpuForUniAppRespDTO();
        List<ProductSpuForUniAppRespDTO.Sku> spuList = new ArrayList<>();
        Map<String, List<ProductSpuForUniAppRespDTO.SpecVal>> specMap = new HashMap<>();
        if (CollUtil.isEmpty(bean.getSkus())) {
            respDTO.setSkuList(spuList);
            respDTO.setSpecList(List.of());
            return respDTO;
        }
        int groupPrice = getMinValue(bean.getSkus(), AppProductSkuRespVO::getPrice);
        for (AppProductSkuRespVO skuDO : bean.getSkus()) {
            ProductSpuForUniAppRespDTO.Sku sku = new ProductSpuForUniAppRespDTO.Sku();
            sku.setId(skuDO.getId());
            sku.setGoodsId(bean.getId());
            sku.setGoodsName(bean.getName());
            if (StrUtil.isBlank(skuDO.getPicUrl())) {
                sku.setImage(bean.getPicUrl());
            }
            sku.setImage(skuDO.getPicUrl());
            sku.setPrice(skuDO.getPrice());
            sku.setGroupPrice(groupPrice);
            sku.setStock(skuDO.getStock());
            for (ProductPropertyValueRespDTO property : skuDO.getProperties()) {
                List<ProductSpuForUniAppRespDTO.SpecVal> vals = specMap.get(property.getPropertyName());
                if (vals == null) {
                    vals = new ArrayList<>();
                }
                List<String> nameList = vals.stream().map(ProductSpuForUniAppRespDTO.SpecVal::getName).toList();
                if (!CollUtil.contains(nameList, property.getValueName())) {
                    ProductSpuForUniAppRespDTO.SpecVal val = new ProductSpuForUniAppRespDTO.SpecVal();
                    val.setId(property.getValueId());
                    val.setName(property.getValueName());
                    vals.add(val);
                }
                specMap.put(property.getPropertyName(), vals);
            }
            // 坑：sku_name_arr 里条目的顺序必须和 spec_list 里条目的顺序一致
            sku.setSpecValueIds(skuDO.getProperties().stream()
                    .sorted(Comparator.comparing(ProductPropertyValueRespDTO::getPropertyName))
                    .map(ProductPropertyValueRespDTO::getValueId)
                    .toList());
            sku.setSkuNameArr(skuDO.getProperties().stream()
                    .sorted(Comparator.comparing(ProductPropertyValueRespDTO::getPropertyName))
                    .map(ProductPropertyValueRespDTO::getValueName)
                    .toList());
            spuList.add(sku);
        }
        respDTO.setSkuList(spuList);
        respDTO.setSpecList(specMap.entrySet().stream()
                // 坑：spec_list 里条目的顺序必须和 sku_name_arr 里条目的顺序一致
                .sorted(Map.Entry.comparingByKey())
                .map(entry -> {
                    ProductSpuForUniAppRespDTO.SpecGroup specGroup = new ProductSpuForUniAppRespDTO.SpecGroup();
                    specGroup.setName(entry.getKey());
                    specGroup.setList(entry.getValue());
                    return specGroup;
                })
                .toList());
        return respDTO;
    }

    AppProductSpuRespVO convertGrouponPackage(GrouponPackageRespDTO dto);

}
